export function findP(vnode, func) {
  if (func(vnode)) return vnode;
  if (vnode.children?.length) {
    let found;
    for (const c of vnode.children)
      if (found = findP(c))
        return found;
  }
}

/** 针对某个vnode的操作扩展
 * 使用方法：
 * 1. 定义组件使用injectRender方法
 * 2. 继承或混入组件
 * 3. 重写__vnodeByRoot或__vnodeByFilter来找到目标vnode，如果适用于组件的根vnode则不需要重写
 * 4. 注入render2方法，通过this.getVNode(vnode)找到目标vnode
 * 5. 对vnode进行你的扩展操作
 * 
 * 完整示例代码如下
 * @example
 * import withvnode from '../__mixin/withvnode'
 * 
 * // 注意使用injectRender
 * export default injectRender({
 *   extends: withvnode,  // 继承
 *   mixins: [withvnode], // 或者混入
 *   methods: {
 *     // 假如目标vnode是根vnode的第2个子节点
 *     __vnodeByRoot(root) { return root.children[1] },
 *   },
 *   // 注入render2
 *   render2(vnode) {
 *     const target = this.getVNode(vnode);
 *     if (target) {
 *       // todo: 对目标节点注入你的操作
 *     }
 *   }
 * })
 */
export default {
  methods: {
    /** 通过根vnode自己根据模板层级返回目标节点 */
    __vnodeByRoot(root) { return root; },
    /** __vnodeByFilter(vnode)，用于继承类重写
     * 通过传入vnode，判断是否是想要的vnode
     * 重写此方法时优先级大于__vnodeByRoot
     * 没有找到目标vnode时，才会采用__vnodeByRoot的结果
     */
    __vnodeByFilter: undefined,
    /** 传入根vnode找到的目标vnode以进行组件操作 */
    getVNode(root) {
      let found;
      if (this.__vnodeByFilter)
        found = findP(root, this.__vnodeByFilter);
      if (!found)
        found = this.__vnodeByRoot(root);
      return found;
    },
  },
}